#define LIBTELNET_IMPLEMENTATION
#include "libtelnet.h"
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#ifdef _WIN32
#include <conio.h>
#include <windows.h>

#else
#include <poll.h>
#include <termios.h>
#include <unistd.h>

#endif

/* 全局变量 */
telnet_session *g_session = NULL;
int g_running = 1;

#ifdef __unix__
struct termios g_old_termios;
#endif

/* 终端设置 - 跨平台实现 */
void set_terminal_mode(int raw) {
#ifdef __unix__
    if (raw) {
        // 保持原始模式，但启用回显（方便用户看到输入）
        tcgetattr(STDIN_FILENO, &g_old_termios);
        struct termios new_termios = g_old_termios;
        new_termios.c_lflag &= ~ICANON;  // 禁用规范模式（不等待回车）
        new_termios.c_lflag |= ECHO;     // 启用回显
        new_termios.c_cc[VMIN] = 1;
        new_termios.c_cc[VTIME] = 0;
        tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
    } else {
        tcsetattr(STDIN_FILENO, TCSANOW, &g_old_termios);
    }
#else
    /* Windows 终端模式设置 */
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    DWORD mode;
    GetConsoleMode(hStdin, &mode);
    
    if (raw) {
        // 启用行输入和回显（按回车才提交）
        SetConsoleMode(hStdin, mode | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
    } else {
        // 恢复原始模式
        SetConsoleMode(hStdin, mode);
    }
#endif
}

/* 清理函数 */
/* 清理函数（增强版） */
void cleanup(void) {
    printf("\nCleaning up resources...\n");
    // 确保终端模式恢复
    set_terminal_mode(0);
    if (g_session) {
        telnet_disconnect(g_session);
        telnet_destroy(g_session);
        g_session = NULL;
    }
}



/* 信号处理 */
/* 信号处理函数（增强版） */
void signal_handler(int signum) {
    if (signum == SIGINT || signum == SIGTERM) {
        printf("\nReceived exit signal, cleaning up...\n");
        // 强制恢复终端模式
        set_terminal_mode(0);
        g_running = 0;
        // 主动断开连接
        if (g_session) {
            telnet_disconnect(g_session);
        }
        // 直接退出程序（避免阻塞）
        exit(0);
    }
}

/* 事件处理回调 */
void handle_event(telnet_session *session, const telnet_event *event) {
  switch (event->type) {
  case TELNET_EVENT_CONNECTED:
    printf("=== Connected to server ===\n");
    break;

  case TELNET_EVENT_DATA:
    /* 输出接收到的数据 */
    fwrite(event->event.data.data, 1, event->event.data.length, stdout);
    fflush(stdout);
    break;

  case TELNET_EVENT_DISCONNECTED:
    printf("\n=== Disconnected from server ===\n");
    g_running = 0;
    break;

  case TELNET_EVENT_ERROR:
    printf("\n=== Error: %s ===\n", event->event.error.message);
    g_running = 0;
    break;
  }
}



/* 检查用户输入 */
int has_user_input() {
#ifdef _WIN32
  return _kbhit();
#else
  struct pollfd pfd;
  pfd.fd = STDIN_FILENO;
  pfd.events = POLLIN;
  return poll(&pfd, 1, 0) > 0;
#endif
}

/* 读取用户输入 */
/* 读取用户输入（修改为行模式） */
int read_user_input(char *buffer, size_t max_len) {
  static size_t input_pos = 0; // 静态变量，保存当前输入位置

#ifdef _WIN32
  char c = _getch();

  // 处理退格键
  if (c == '\b' && input_pos > 0) {
    input_pos--;
    printf("\b \b"); // 清除屏幕上的字符
    buffer[input_pos] = '\0';
    return 0;
  }
  // 处理回车键
  else if (c == '\r') {
    buffer[input_pos] = '\n'; // 转换为换行符
    input_pos++;
    printf("\r\n"); // 显示换行
    int len = input_pos;
    input_pos = 0; // 重置输入位置
    return len;
  }
  // 普通字符
  else if (input_pos < max_len - 1) {
    buffer[input_pos++] = c;
    printf("%c", c); // 回显输入
    return 0;
  }
  return 0;
#else
  // 类Unix系统行模式处理（简化版）
  ssize_t n = read(STDIN_FILENO, buffer, max_len - 1);
  if (n > 0) {
    // 替换回车为换行（可选）
    for (int i = 0; i < n; i++) {
      if (buffer[i] == '\r') {
        buffer[i] = '\n';
      }
    }
    return n;
  }
  return 0;
#endif
}

int main(int argc, char *argv[]) {
  const char *host = "localhost";
  uint16_t port = 2323;

  /* 解析命令行参数 */
  if (argc >= 2) {
    host = argv[1];
  }
  if (argc >= 3) {
    port = (uint16_t)atoi(argv[2]);
  }

  printf("Telnet Test Client\n");
  printf("Connecting to %s:%d...\n", host, port);

  /* 注册清理函数和信号处理 */
  atexit(cleanup);
  signal(SIGINT, signal_handler);
  signal(SIGTERM, signal_handler);

  /* 创建telnet会话 */
  g_session = telnet_create(4096);
  if (!g_session) {
    fprintf(stderr, "Failed to create telnet session\n");
    return 1;
  }

  /* 连接到测试服务器 */
  if (telnet_connect(g_session, host, port) != 0) {
    fprintf(stderr, "Failed to connect to %s:%d\n", host, port);
    return 1;
  }

  /* 设置终端模式 */
  set_terminal_mode(1);

  /* 主事件循环 */
  printf("Connected. Type 'exit' to quit, or Ctrl+C to terminate.\n");
  while (g_running && g_session->state == TELNET_STATE_CONNECTED) {
    /* 处理telnet事件 */
    telnet_process(g_session, handle_event);

    /* 主事件循环中处理输入的部分（修改） */
    if (has_user_input()) {
      char buffer[1024];
      int bytes_read = read_user_input(buffer, sizeof(buffer));

      if (bytes_read > 0) { // 只有当检测到回车时，bytes_read才会大于0
        /* 发送用户输入到服务器 */
        telnet_send(g_session, buffer, bytes_read);

        /* 检查是否要退出 */
        if (strncmp(buffer, "exit", 4) == 0) {
          g_running = 0;
        }
      }
    }

    /* 短暂休眠，减少CPU占用 */
#ifdef _WIN32
    Sleep(10);
#else
    usleep(10000);
#endif
  }

  /* 恢复终端模式 */
  set_terminal_mode(0);
  printf("Test completed.\n");

  return 0;
}
